﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Klinkby.MicroBus
{
    static class Safe
    {
        [DebuggerStepThrough]
        public static T Validate<T>(T value, Func<bool> validation, string errorMessage)
        {
            if (!validation())
                throw new ArgumentException(errorMessage);
            return value;
        }

        [DebuggerStepThrough]
        public static T NonNull<T>(T value, string parameterName)
            where T : class
        {
            if (value == null)
                throw new ArgumentNullException(parameterName);
            return value;
        }

        [DebuggerStepThrough]
        public static void Raise(EventHandler handler, object sender)
        {
            if (handler != null)
                handler(sender, EventArgs.Empty);
        }

        [DebuggerStepThrough]
        public static int RaiseAsync(EventHandler handler, object sender)
        {
            int count = 0;
            if (handler != null)
            {
                var listeners = handler.GetInvocationList();
                count = listeners.Length;
                if (count > 1)
                {
                    Parallel.ForEach(listeners, (listener) => ((EventHandler)listener)(sender, EventArgs.Empty));
                }
                else
                    ((EventHandler)listeners[0])(sender, EventArgs.Empty);
            }
            return count;
        }

        [DebuggerStepThrough]
        public static void Raise<T>(EventHandler<T> handler, object sender, T e)
            where T : EventArgs
        {
            if (handler != null)
                handler(sender, e);
        }

        [DebuggerStepThrough]
        public static int RaiseAsync<T>(EventHandler<T> handler, object sender, T e)
            where T : EventArgs
        {
            int count = 0;
            if (handler != null)
            {
                var listeners = handler.GetInvocationList();
                count = listeners.Length;
                if (count > 1)
                {
                    Parallel.ForEach(listeners, (listener) => ((EventHandler<T>)listener)(sender, e));
                }
                else
                    ((EventHandler<T>)listeners[0])(sender, e);
            }
            return count;
        }
    }
}
